home *** CD-ROM | disk | FTP | other *** search
/ Internet Surfer 2.0 / Internet Surfer 2.0 (Wayzata Technology) (1996).iso / pc / text / mac / faqs.221 < prev    next >
Text File  |  1996-02-12  |  29KB  |  722 lines

  1. Frequently Asked Questions (FAQS);faqs.221
  2.  
  3.  
  4.  
  5. Besides listing frequently-asked questions, this article also summarizes
  6. frequently-posted answers.  Even if you know all the answers, it's worth
  7. skimming through this list once in a while, so that when you see one of
  8. its questions unwittingly posted, you won't have to waste time
  9. answering.
  10.  
  11. This article is always being improved.  Your input is welcomed.  Send
  12. your comments to scs@adam.mit.edu, scs%adam.mit.edu@mit.edu, and/or
  13. mit-eddie!adam.mit.edu!scs; this article's From: line may be unusable.
  14.  
  15. The questions answered here are divided into several categories:
  16.  
  17.      1. Null Pointers
  18.      2. Arrays and Pointers
  19.      3. Memory Allocation
  20.      4. Expressions
  21.      5. ANSI C
  22.      6. C Preprocessor
  23.      7. Variable-Length Argument Lists
  24.      8. Boolean Expressions and Variables
  25.      9. Structs, Enums, and Unions
  26.     10. Declarations
  27.     11. Stdio
  28.     12. Library Subroutines
  29.     13. Lint
  30.     14. Style
  31.     15. Floating Point
  32.     16. System Dependencies
  33.     17. Miscellaneous (Fortran to C converters, YACC grammars, etc.)
  34.  
  35. Herewith, some frequently-asked questions and their answers:
  36.  
  37.  
  38. Section 1. Null Pointers
  39.  
  40. 1.1:    What is this infamous null pointer, anyway?
  41.  
  42. A:    The language definition states that for each pointer type, there
  43.     is a special value -- the "null pointer" -- which is
  44.     distinguishable from all other pointer values and which is not
  45.     the address of any object.  That is, the address-of operator &
  46.     will never yield a null pointer, nor will a successful call to
  47.     malloc.  (malloc returns a null pointer when it fails, and this
  48.     is a typical use of null pointers: as a "special" pointer value
  49.     with some other meaning, usually "not allocated" or "not
  50.     pointing anywhere yet.")
  51.  
  52.     A null pointer is conceptually different from an uninitialized
  53.     pointer.  A null pointer is known not to point to any object; an
  54.     uninitialized pointer might point anywhere.  See also questions
  55.     3.1, 3.9, and 17.1.
  56.  
  57.     As mentioned in the definition above, there is a null pointer
  58.     for each pointer type, and the internal values of null pointers
  59.     for different types may be different.  Although programmers need
  60.     not know the internal values, the compiler must always be
  61.     informed which type of null pointer is required, so it can make
  62.     the distinction if necessary (see below).
  63.  
  64.     References: K&R I Sec. 5.4 pp. 97-8; K&R II Sec. 5.4 p. 102; H&S
  65.     Sec. 5.3 p. 91; ANSI Sec. 3.2.2.3 p. 38.
  66.  
  67. 1.2:    How do I "get" a null pointer in my programs?
  68.  
  69. A:    According to the language definition, a constant 0 in a pointer
  70.     context is converted into a null pointer at compile time.  That
  71.     is, in an initialization, assignment, or comparison when one
  72.     side is a variable or expression of pointer type, the compiler
  73.     can tell that a constant 0 on the other side requests a null
  74.     pointer, and generate the correctly-typed null pointer value.
  75.     Therefore, the following fragments are perfectly legal:
  76.  
  77.         char *p = 0;
  78.         if(p != 0)
  79.  
  80.     However, an argument being passed to a function is not
  81.     necessarily recognizable as a pointer context, and the compiler
  82.     may not be able to tell that an unadorned 0 "means" a null
  83.     pointer.  For instance, the Unix system call "execl" takes a
  84.     variable-length, null-pointer-terminated list of character
  85.     pointer arguments.  To generate a null pointer in a function
  86.     call context, an explicit cast is typically required, to force
  87.     the 0 to be in a pointer context:
  88.  
  89.         execl("/bin/sh", "sh", "-c", "ls", (char *)0);
  90.  
  91.     If the (char *) cast were omitted, the compiler would not know
  92.     to pass a null pointer, and would pass an integer 0 instead.
  93.     (Note that many Unix manuals get this example wrong.)
  94.  
  95.     When function prototypes are in scope, argument passing becomes
  96.     an "assignment context," and most casts may safely be omitted,
  97.     since the prototype tells the compiler that a pointer is
  98.     required, and of which type, enabling it to correctly convert
  99.     unadorned 0's.  Function prototypes cannot provide the types for
  100.     variable arguments in variable-length argument lists, however,
  101.     so explicit casts are still required for those arguments.  It is
  102.     safest always to cast null pointer function arguments, to guard
  103.     against varargs functions or those without prototypes, to allow
  104.     interim use of non-ANSI compilers, and to demonstrate that you
  105.     know what you are doing.  (Incidentally, it's also a simpler
  106.     rule to remember.)
  107.  
  108.     Summary:
  109.  
  110.         Unadorned 0 okay:    Explicit cast required:
  111.  
  112.         initialization        function call,
  113.                     no prototype in scope
  114.         assignment
  115.                     variable argument in
  116.         comparison        varargs function call
  117.  
  118.         function call,
  119.         prototype in scope,
  120.         fixed argument
  121.  
  122.     References: K&R I Sec. A7.7 p. 190, Sec. A7.14 p. 192; K&R II
  123.     Sec. A7.10 p. 207, Sec. A7.17 p. 209; H&S Sec. 4.6.3 p. 72; ANSI
  124.     Sec. 3.2.2.3 .
  125.  
  126. 1.3:    What is NULL and how is it #defined?
  127.  
  128. A:    As a matter of style, many people prefer not to have unadorned
  129.     0's scattered throughout their programs.  For this reason, the
  130.     preprocessor macro NULL is #defined (by <stdio.h> or
  131.     <stddef.h>), with value 0 (or (void *)0, about which more
  132.     later).  A programmer who wishes to make explicit the
  133.     distinction between 0 the integer and 0 the null pointer can
  134.     then use NULL whenever a null pointer is required.  This is a
  135.     stylistic convention only; the preprocessor turns NULL back to 0
  136.     which is then recognized by the compiler (in pointer contexts)
  137.     as before.  In particular, a cast may still be necessary before
  138.     NULL (as before 0) in a function call argument.  (The table
  139.     under question 1.2 above applies for NULL as well as 0.)
  140.  
  141.     NULL should _only_ be used for pointers; see question 1.8.
  142.  
  143.     References: K&R I Sec. 5.4 pp. 97-8; K&R II Sec. 5.4 p. 102; H&S
  144.     Sec. 13.1 p. 283; ANSI Sec. 4.1.5 p. 99, Sec. 3.2.2.3 p. 38,
  145.     Rationale Sec. 4.1.5 p. 74.
  146.  
  147. 1.4:    How should NULL be #defined on a machine which uses a nonzero
  148.     bit pattern as the internal representation of a null pointer?
  149.  
  150. A:    Programmers should never need to know the internal
  151.     representation(s) of null pointers, because they are normally
  152.     taken care of by the compiler.  If a machine uses a nonzero bit
  153.     pattern for null pointers, it is the compiler's responsibility
  154.     to generate it when the programmer requests, by writing "0" or
  155.     "NULL," a null pointer.  Therefore, #defining NULL as 0 on a
  156.     machine for which internal null pointers are nonzero is as valid
  157.     as on any other, because the compiler must (and can) still
  158.     generate the machine's correct null pointers in response to
  159.     unadorned 0's seen in pointer contexts.
  160.  
  161. 1.5:    If NULL were defined as follows:
  162.  
  163.         #define NULL (char *)0
  164.  
  165.     wouldn't that make function calls which pass an uncast NULL
  166.     work?
  167.  
  168. A:    Not in general.  The problem is that there are machines which
  169.     use different internal representations for pointers to different
  170.     types of data.  The suggested #definition would make uncast NULL
  171.     arguments to functions expecting pointers to characters to work
  172.     correctly, but pointer arguments to other types would still be
  173.     problematical, and legal constructions such as
  174.  
  175.         FILE *fp = NULL;
  176.  
  177.     could fail.
  178.  
  179.     Nevertheless, ANSI C allows the alternate
  180.  
  181.         #define NULL ((void *)0)
  182.  
  183.     definition for NULL.  Besides helping incorrect programs to work
  184.     (but only on machines with homogeneous pointers, thus
  185.     questionably valid assistance) this definition may catch
  186.     programs which use NULL incorrectly (e.g. when the ASCII  NUL
  187.     character was really intended; see question 1.8).
  188.  
  189. 1.6:    I use the preprocessor macro
  190.  
  191.         #define Nullptr(type) (type *)0
  192.  
  193.     to help me build null pointers of the correct type.
  194.  
  195. A:    This trick, though popular in some circles, does not buy much.
  196.     It is not needed in assignments and comparisons; see question
  197.     1.2.  It does not even save keystrokes.  Its use suggests to the
  198.     reader that the author is shaky on the subject of null pointers,
  199.     and requires the reader to check the #definition of the macro,
  200.     its invocations, and _all_ other pointer usages much more
  201.     carefully.  See also question 8.1.
  202.  
  203. 1.7:    Is the abbreviated pointer comparison "if(p)" to test for non-
  204.     null pointers valid?  What if the internal representation for
  205.     null pointers is nonzero?
  206.  
  207. A:    When C requires the boolean value of an expression (in the if,
  208.     while, for, and do statements, and with the &&, ||, !, and ?:
  209.     operators), a false value is produced when the expression
  210.     compares equal to zero, and a true value otherwise.  That is,
  211.     whenever one writes
  212.  
  213.         if(expr)
  214.  
  215.     where "expr" is any expression at all, the compiler essentially
  216.     acts as if it had been written as
  217.  
  218.         if(expr != 0)
  219.  
  220.     Substituting the trivial pointer expression "p" for "expr," we
  221.     have
  222.  
  223.         if(p)    is equivalent to        if(p != 0)
  224.  
  225.     and this is a comparison context, so the compiler can tell that
  226.     the (implicit) 0 is a null pointer, and use the correct value.
  227.     There is no trickery involved here; compilers do work this way,
  228.     and generate identical code for both statements.  The internal
  229.     representation of a pointer does _not_ matter.
  230.  
  231.     The boolean negation operator, !, can be described as follows:
  232.  
  233.         !expr    is essentially equivalent to    expr?0:1
  234.  
  235.     It is left as an exercise for the reader to show that
  236.  
  237.         if(!p)    is equivalent to        if(p == 0)
  238.  
  239.     "Abbreviations" such as if(p), though perfectly legal, are
  240.     considered by some to be bad style.
  241.  
  242.     See also question 8.2.
  243.  
  244.     References: K&R II Sec. A7.4.7 p. 204; H&S Sec. 5.3 p. 91; ANSI
  245.     Secs. 3.3.3.3, 3.3.9, 3.3.13, 3.3.14, 3.3.15, 3.6.4.1, and
  246.     3.6.5 .
  247.  
  248. 1.8:    If "NULL" and "0" are equivalent, which should I use?
  249.  
  250. A:    Many programmers believe that "NULL" should be used in all
  251.     pointer contexts, as a reminder that the value is to be thought
  252.     of as a pointer.  Others feel that the confusion surrounding
  253.     "NULL" and "0" is only compounded by hiding "0" behind a
  254.     #definition, and prefer to use unadorned "0" instead.  There is
  255.     no one right answer.  C programmers must understand that "NULL"
  256.     and "0" are interchangeable and that an uncast "0" is perfectly
  257.     acceptable in initialization, assignment, and comparison
  258.     contexts.  Any usage of "NULL" (as opposed to "0") should be
  259.     considered a gentle reminder that a pointer is involved;
  260.     programmers should not depend on it (either for their own
  261.     understanding or the compiler's) for distinguishing pointer 0's
  262.     from integer 0's.
  263.  
  264.     NULL should _not_ be used when another kind of 0 is required,
  265.     even though it might work, because doing so sends the wrong
  266.     stylistic message.  (ANSI allows the #definition of NULL to be
  267.     (void *)0, which will not work in non-pointer contexts.)  In
  268.     particular, do not use NULL when the ASCII null character (NUL)
  269.     is desired.  Provide your own definition
  270.  
  271.         #define NUL '\0'
  272.  
  273.     if you must.
  274.  
  275.     Reference: K&R II Sec. 5.4 p. 102.
  276.  
  277. 1.9:    But wouldn't it be better to use NULL (rather than 0) in case
  278.     the value of NULL changes, perhaps on a machine with nonzero
  279.     null pointers?
  280.  
  281. A:    No.  Although symbolic constants are often used in place of
  282.     numbers because the numbers might change, this is _not_ the
  283.     reason that NULL is used in place of 0.  Once again, the
  284.     language guarantees that source-code 0's (in pointer contexts)
  285.     generate null pointers.  NULL is used only as a stylistic
  286.     convention.
  287.  
  288. 1.10:    I'm confused.  NULL is guaranteed to be 0, but the null pointer
  289.     is not?
  290.  
  291. A:    When the term "null" or "NULL" is casually used, one of several
  292.     things may be meant:
  293.  
  294.     1.    The conceptual null pointer, the abstract language
  295.         concept defined in question 1.1.  It is implemented
  296.         with...
  297.  
  298.     2.    The internal (or run-time) representation of a null
  299.         pointer, which may or may not be all-bits-0 and which
  300.         may be different for different pointer types.  The
  301.         actual values should be of concern only to compiler
  302.         writers.  Authors of C programs never see them, since
  303.         they use...
  304.  
  305.     3.    The source code syntax for null pointers, which is the
  306.         single character "0".  It is often hidden behind...
  307.  
  308.     4.    The NULL macro, which is #defined to be "0" or
  309.         "(void *)0".  Finally, as red herrings, we have...
  310.  
  311.     5.    The ASCII null character (NUL), which does have all bits
  312.         zero, but has no relation to the null pointer except in
  313.         name; and...
  314.  
  315.     6.    The "null string," which is another name for an empty
  316.         string ("").  The term "null string" can be confusing in
  317.         C (and should perhaps be avoided), because it involves a
  318.         null ('\0') character, but not a null pointer, which
  319.         brings us full circle...
  320.  
  321.     This article always uses the phrase "null pointer" (in lower
  322.     case) for sense 1, the character "0" for sense 3, and the
  323.     capitalized word "NULL" for sense 4.
  324.  
  325. 1.11:    Why is there so much confusion surrounding null pointers?  Why
  326.     do these questions come up so often?
  327.  
  328. A:    C programmers traditionally like to know more than they need to
  329.     about the underlying machine implementation.  The fact that null
  330.     pointers are represented both in source code, and internally to
  331.     most machines, as zero invites unwarranted assumptions.  The use
  332.     of a preprocessor macro (NULL) suggests that the value might
  333.     change later, or on some weird machine.  The construct
  334.     "if(p == 0)" is easily misread as calling for conversion of p to
  335.     an integral type, rather than 0 to a pointer type, before the
  336.     comparison.  Finally, the distinction between the several uses
  337.     of the term "null" (listed above) is often overlooked.
  338.  
  339.     One good way to wade out of the confusion is to imagine that C
  340.     had a keyword (perhaps "nil", like Pascal) with which null
  341.     pointers were requested.  The compiler could either turn "nil"
  342.     into the correct type of null pointer, when it could determine
  343.     the type from the source code, or complain when it could not.
  344.     Now, in fact, in C the keyword for a null pointer is not "nil"
  345.     but "0", which works almost as well, except that an uncast "0"
  346.     in a non-pointer context generates an integer zero instead of an
  347.     error message, and if that uncast 0 was supposed to be a null
  348.     pointer, the code may not work.
  349.  
  350. 1.12:    I'm still confused.  I just can't understand all this null
  351.     pointer stuff.
  352.  
  353. A:    Follow these two simple rules:
  354.  
  355.     1.    When you want to refer to a null pointer in source code,
  356.         use "0" or "NULL".
  357.  
  358.     2.    If the usage of "0" or "NULL" is an argument in a
  359.         function call, cast it to the pointer type expected by
  360.         the function being called.
  361.  
  362.     The rest of the discussion has to do with other people's
  363.     misunderstandings, or with the internal representation of null
  364.     pointers (which you shouldn't need to know), or with ANSI C
  365.     refinements.  Understand questions 1.1, 1.2, and 1.3, and
  366.     consider 1.8 and 1.11, and you'll do fine.
  367.  
  368. 1.13:    Given all the confusion surrounding null pointers, wouldn't it
  369.     be easier simply to require them to be represented internally by
  370.     zeroes?
  371.  
  372. A:    If for no other reason, doing so would be ill-advised because it
  373.     would unnecessarily constrain implementations which would
  374.     otherwise naturally represent null pointers by special, nonzero
  375.     bit patterns, particularly when those values would trigger
  376.     automatic hardware traps for invalid accesses.
  377.  
  378.     Besides, what would this requirement really accomplish?  Proper
  379.     understanding of null pointers does not require knowledge of the
  380.     internal representation, whether zero or nonzero.  Assuming that
  381.     null pointers are internally zero does not make any code easier
  382.     to write (except for a certain ill-advised usage of calloc; see
  383.     question 3.9).  Known-zero internal pointers would not obviate
  384.     casts in function calls, because the _size_ of the pointer might
  385.     still be different from that of an int.  (If "nil" were used to
  386.     request null pointers rather than "0," as mentioned in question
  387.     1.11, the urge to assume an internal zero representation would
  388.     not even arise.)
  389.  
  390. 1.14:    Seriously, have any actual machines really used nonzero null
  391.     pointers, or different representations for pointers to different
  392.     types?
  393.  
  394. A:    The Prime 50 series used segment 07777, offset 0 for the null
  395.     pointer, at least for PL/I.  Later models used segment 0, offset
  396.     0 for null pointers in C, necessitating new instructions such as
  397.     TCNP (Test C Null Pointer), evidently as a sop to all the extant
  398.     poorly-written C code which made incorrect assumptions.  Older,
  399.     word-addressed Prime machines were also notorious for requiring
  400.     larger byte pointers (char *'s) than word pointers (int *'s).
  401.  
  402.     Some Honeywell-Bull mainframes use the bit pattern 06000 for
  403.     (internal) null pointers.
  404.  
  405.     The Symbolics Lisp Machine, a tagged architecture, does not even
  406.     have conventional numeric pointers; it uses the pair <NIL, 0>
  407.     (basically a nonexistent <object, offset> handle) as a C null
  408.     pointer.
  409.  
  410.     Depending on the "memory model" in use, 80*86 processors (PC's)
  411.     may use 16 bit data pointers and 32 bit function pointers, or
  412.     vice versa.
  413.  
  414.  
  415. Section 2. Arrays and Pointers
  416.  
  417. 2.1:    I had the definition char a[6] in one source file, and in
  418.     another I declared extern char *a.  Why didn't it work?
  419.  
  420. A:    The declaration extern char *a simply does not match the actual
  421.     definition.  The type "pointer-to-type-T" is not the same as
  422.     "array-of-type-T."  Use extern char a[].
  423.  
  424.     References: CT&P Sec. 3.3 pp. 33-4, Sec. 4.5 pp. 64-5.
  425.  
  426. 2.2:    But I heard that char a[] was identical to char *a.
  427.  
  428. A:    Not at all.  (What you heard has to do with formal parameters to
  429.     functions; see question 2.4.)  Arrays are not pointers.  The
  430.     array declaration "char a[6];" requests that space for six
  431.     characters be set aside, to be known by the name "a."  That is,
  432.     there is a location named "a" at which six characters can sit.
  433.     The pointer declaration "char *p;" on the other hand, requests a
  434.     place which holds a pointer.  The pointer is to be known by the
  435.     name "p," and can point to any char (or contiguous array of
  436.     chars) anywhere.
  437.  
  438.     As usual, a picture is worth a thousand words.  The statements
  439.  
  440.         char a[] = "hello";
  441.         char *p = "world";
  442.  
  443.     would result in data structures which could be represented like
  444.     this:
  445.  
  446.            +---+---+---+---+---+---+
  447.         a: | h | e | l | l | o |\0 |
  448.            +---+---+---+---+---+---+
  449.  
  450.            +-----+     +---+---+---+---+---+---+
  451.         p: |  *======> | w | o | r | l | d |\0 |
  452.            +-----+     +---+---+---+---+---+---+
  453.  
  454.     It is important to remember that a reference like x[3] generates
  455.     different code depending on whether x is an array or a pointer.
  456.     Given the declarations above, when the compiler sees the
  457.     expression a[3], it emits code to start at the location "a,"
  458.     move three past it, and fetch the character there.  When it sees
  459.     the expression p[3], it emits code to start at the location "p,"
  460.     fetch the pointer value there, add three to the pointer, and
  461.     finally fetch the character pointed to.  In the example above,
  462.     both a[3] and p[3] happen to be the character 'l', but the
  463.     compiler gets there differently.  (See also question 17.14.)
  464.  
  465. 2.3:    So what is meant by the "equivalence of pointers and arrays" in
  466.     C?
  467.  
  468. A:    Much of the confusion surrounding pointers in C can be traced to
  469.     a misunderstanding of this statement.  Saying that arrays and
  470.     pointers are "equivalent" does not by any means imply that they
  471.     are interchangeable.
  472.  
  473.     "Equivalence" refers to the following key definition:
  474.  
  475.         An lvalue of type array-of-T which appears in an
  476.         expression decays (with three exceptions) into a
  477.         pointer to its first element; the type of the
  478.         resultant pointer is pointer-to-T.
  479.  
  480.     (The exceptions are when the array is the operand of a sizeof or
  481.     & operator, or is a literal string initializer for a character
  482.     array.)
  483.  
  484.     As a consequence of this definition, there is not really any
  485.     difference in the behavior of the "array subscripting" operator
  486.     [] as it applies to arrays and pointers.  In an expression of
  487.     the form a[i], the array reference "a" decays into a pointer,
  488.     following the rule above, and is then subscripted exactly as
  489.     would be a pointer variable in the expression p[i].  In either
  490.     case, the expression x[i] (where x is an array or a pointer) is,
  491.     by definition, exactly equivalent to *((x)+(i)).
  492.  
  493.     References: K&R I Sec. 5.3 pp. 93-6; K&R II Sec. 5.3 p. 99; H&S
  494.     Sec. 5.4.1 p. 93; ANSI Sec. 3.2.2.1, Sec. 3.3.2.1, Sec. 3.3.6 .
  495.  
  496. 2.4:    Then why are array and pointer declarations interchangeable as
  497.     function formal parameters?
  498.  
  499. A:    Since arrays decay immediately into pointers, an array is never
  500.     actually passed to a function.  As a convenience, any parameter
  501.     declarations which "look like" arrays, e.g.
  502.  
  503.         f(a)
  504.         char a[];
  505.  
  506.     are treated by the compiler as if they were pointers, since that
  507.     is what the function will receive if an array is passed:
  508.  
  509.         f(a)
  510.         char *a;
  511.  
  512.     This conversion holds only within function formal parameter
  513.     declarations, nowhere else.  If this conversion bothers you,
  514.     avoid it; many people have concluded that the confusion it
  515.     causes outweighs the small advantage of having the declaration
  516.     "look like" the call and/or the uses within the function.
  517.  
  518.     References: K&R I Sec. 5.3 p. 95, Sec. A10.1 p. 205; K&R II
  519.     Sec. 5.3 p. 100, Sec. A8.6.3 p. 218, Sec. A10.1 p. 226; H&S
  520.     Sec. 5.4.3 p. 96; ANSI Sec. 3.5.4.3, Sec. 3.7.1, CT&P Sec. 3.3
  521.     pp. 33-4.
  522.  
  523. 2.5:    Why doesn't sizeof properly report the size of an array which is
  524.     a parameter to a function?
  525.  
  526. A:    The sizeof operator reports the size of the pointer parameter
  527.     which the function actually receives (see question 2.4).
  528.  
  529. 2.6:    Someone explained to me that arrays were really just constant
  530.     pointers.
  531.  
  532. A:    This is a bit of an oversimplification.  An array name is
  533.     "constant" in that it cannot be assigned to, but an array is
  534.     _not_ a pointer, as the discussion and pictures in question 2.2
  535.     should make clear.
  536.  
  537. 2.7:    I came across some "joke" code containing the "expression"
  538.     5["abcdef"] .  How can this be legal C?
  539.  
  540. A:    Yes, Virginia, array subscripting is commutative in C.  This
  541.     curious fact follows from the pointer definition of array
  542.     subscripting, namely that a[e] is exactly equivalent to
  543.     *((a)+(e)), for _any_ expression e and primary expression a, as
  544.     long as one of them is a pointer expression and one is integral.
  545.     This unsuspected commutativity is often mentioned in C texts as
  546.     if it were something to be proud of, but it finds no useful
  547.     application outside of the Obfuscated C Contest (see question
  548.     17.9).
  549.  
  550.     References: ANSI Rationale Sec. 3.3.2.1 p. 41.
  551.  
  552. 2.8:    My compiler complained when I passed a two-dimensional array to
  553.     a routine expecting a pointer to a pointer.
  554.  
  555. A:    The rule by which arrays decay into pointers is not applied
  556.     recursively.  An array of arrays (i.e. a two-dimensional array
  557.     in C) decays into a pointer to an array, not a pointer to a
  558.     pointer.  Pointers to arrays can be confusing, and must be
  559.     treated carefully.  (The confusion is heightened by the
  560.     existence of incorrect compilers, including some versions of pcc
  561.     and pcc-derived lint's, which improperly accept assignments of
  562.     multi-dimensional arrays to multi-level pointers.)  If you are
  563.     passing a two-dimensional array to a function:
  564.  
  565.         int array[YSIZE][XSIZE];
  566.         f(array);
  567.  
  568.     the function's declaration should match:
  569.  
  570.         f(int a[][XSIZE]) {...}
  571.     or
  572.         f(int (*ap)[XSIZE]) {...}    /* ap is a pointer to an array */
  573.  
  574.     In the first declaration, the compiler performs the usual
  575.     implicit parameter rewriting of "array of array" to "pointer to
  576.     array;" in the second form the pointer declaration is explicit.
  577.     Since the called function does not allocate space for the array,
  578.     it does not need to know the overall size, so the number of
  579.     "rows," YSIZE, can be omitted.  The "shape" of the array is
  580.     still important, so the "column" dimension XSIZE (and, for 3- or
  581.     more dimensional arrays, the intervening ones) must be included.
  582.  
  583.     If a function is already declared as accepting a pointer to a
  584.     pointer, it is probably incorrect to pass a two-dimensional
  585.     array directly to it.
  586.  
  587.     References: K&R I Sec. 5.10 p. 110; K&R II Sec. 5.9 p. 113.
  588.  
  589. 2.9:    How do I declare a pointer to an array?
  590.  
  591. A:    Usually, you don't want to.  Consider using a pointer to one of
  592.     the array's elements instead.  Arrays of type T decay into
  593.     pointers to type T (see question 2.3), which is convenient;
  594.     subscripting or incrementing the resultant pointer accesses the
  595.     individual members of the array.  True pointers to arrays, when
  596.     subscripted or incremented, step over entire arrays, and are
  597.     generally only useful when operating on arrays of arrays, if at
  598.     all.  (See question 2.8 above.)  When people speak casually of a
  599.     pointer to an array, they usually mean a pointer to its first
  600.     element.
  601.  
  602.     If you really need to declare a pointer to an entire array, use
  603.     something like "int (*ap)[N];" where N is the size of the array.
  604.     (See also question 10.3.)  If the size of the array is unknown,
  605.     N can be omitted, but the resulting type, "pointer to array of
  606.     unknown size," is useless.
  607.  
  608. 2.10:    How can I dynamically allocate a multidimensional array?
  609.  
  610. A:    It is usually best to allocate an array of pointers, and then
  611.     initialize each pointer to a dynamically-allocated "row."  The
  612.     resulting "ragged" array can save space, although it is not
  613.     necessarily contiguous in memory as a real array would be.  Here
  614.     is a two-dimensional example:
  615.  
  616.         int **array = (int **)malloc(nrows * sizeof(int *));
  617.         for(i = 0; i < nrows; i++)
  618.             array[i] = (int *)malloc(ncolumns * sizeof(int));
  619.  
  620.     (In "real" code, of course, malloc would be declared correctly,
  621.     and each return value checked.)
  622.  
  623.     You can keep the array's contents contiguous, while making later
  624.     reallocation of individual rows difficult, with a bit of
  625.     explicit pointer arithmetic:
  626.  
  627.         int **array = (int **)malloc(nrows * sizeof(int *));
  628.         array[0] = (int *)malloc(nrows * ncolumns * sizeof(int));
  629.         for(i = 1; i < nrows; i++)
  630.             array[i] = array[0] + i * ncolumns;
  631.  
  632.     In either case, the elements of the dynamic array can be
  633.     accessed with normal-looking array subscripts: array[i][j].
  634.  
  635.     If the double indirection implied by the above schemes is for
  636.     some reason unacceptable, you can simulate a two-dimensional
  637.     array with a single, dynamically-allocated one-dimensional
  638.     array:
  639.  
  640.         int *array = (int *)malloc(nrows * ncolumns * sizeof(int));
  641.  
  642.     However, you must now perform subscript calculations manually,
  643.     accessing the i,jth element with array[i * ncolumns + j].  (A
  644.     macro can hide the explicit calculation, but invoking it then
  645.     requires parentheses and commas which don't look exactly like
  646.     multidimensional array subscripts.)
  647.  
  648.     Finally, you can use pointers-to-arrays:
  649.  
  650.         int (*array)[NCOLUMNS] =
  651.             (int (*)[NCOLUMNS])malloc(nrows * sizeof(*array));
  652.  
  653.     , but the syntax gets horrific and all but one dimension must be
  654.     known at compile time.
  655.  
  656.     With all of these techniques, you may of course need to remember
  657.     to free the arrays (which may take several steps) when they are
  658.     no longer needed.  You must also be extremely cautious when
  659.     passing dynamically-allocated arrays down to other functions, if
  660.     those functions are also to accept conventional, statically-
  661.     allocated arrays (see question 2.8).
  662.  
  663. 2.11:    Here's a neat trick: if I write
  664.  
  665.         int realarray[10];
  666.         int *array = &realarray[-1];
  667.  
  668.     I can treat "array" as if it were a 1-based array.
  669.  
  670. A:    This technique, though attractive, is not strictly conforming to
  671.     the C standards (in spite of its appearance in Numerical Recipes
  672.     in C).  Pointer arithmetic is defined only as long as the
  673.     pointer points within the same allocated block of memory, or to
  674.     the imaginary "terminating" element one past it; otherwise, the
  675.     behavior is undefined, _even if the pointer is not
  676.     dereferenced_.  The code above could fail if, while subtracting
  677.     the offset, an illegal address were generated (perhaps because
  678.     the address tried to "wrap around" past the beginning of some
  679.     memory segment).
  680.  
  681.     References: ANSI Sec. 3.3.6 p. 48, Rationale Sec. 3.2.2.3 p. 38;
  682.     K&R II Sec. 5.3 p. 100, Sec. 5.4 pp. 102-3, Sec. A7.7 pp. 205-6.
  683.  
  684. 2.12:    I passed a pointer to a function which initialized it:
  685.  
  686.         main()
  687.         {
  688.             int *ip;
  689.             f(ip);
  690.             return 0;
  691.         }
  692.  
  693.         void f(ip)
  694.         int *ip;
  695.         {
  696.             static int dummy;
  697.             ip = &dummy;
  698.             *ip = 5;
  699.         }
  700.  
  701.     , but the pointer in the caller was unchanged.
  702.  
  703. A:    Did the function try to initialize the pointer itself, or just
  704.     what it pointed to?  Remember that arguments in C are passed by
  705.     value.  The called function altered only the passed copy of the
  706.     pointer.  You'll want to pass the address of the pointer (the
  707.     function will end up accepting a pointer-to-a-pointer).
  708.  
  709. 2.13:    I have a char * pointer that happens to point to some ints, and
  710.     I want to step it over them.  Why doesn't
  711.  
  712.         ((int *)p)++;
  713.  
  714.     work?
  715.  
  716. A:    In C, a cast operator does not mean "pretend these bits have a
  717.     different type, and treat them accordingly;" it is a conversion
  718.     operator, and by definition it yields an rvalue, which cannot be
  719.     assigned to, or incremented with ++.  (It is an anomaly in pcc-
  720.     derived compilers, and an extension in gcc, that expressions
  721.     such as the above are ever accepted.)  Say what you mean: use
  722.